import Store from '@/store' // 获取 Vuex Store 实例，注意是**实例**，而不是 vuex 这个库
import Config  from '@/assets/js/config.js'
import Utils from '@/uni_modules/yingbing-ui/js_sdk/util.js'
import request from '@/uni_modules/yingbing-request/js_sdk'
import gb2312 from '@/assets/other/gb2312.js'
import Single from '@/assets/constructor/single.js'
import Gather from '@/assets/constructor/gather.js'
import Character from '@/assets/constructor/character.js'
import Section from '@/assets/constructor/section.js'
import Comment from '@/assets/constructor/comment.js'
import Barrage from '@/assets/constructor/barrage.js'
import CryptoJS from "@/assets/crypto-js/crypto-js.js"
import Base64 from "@/assets/other/base64.js"
import HTMLParser from "@/uni_modules/html-parser/js_sdk/index.js"
import inSources from '@/assets/api/source.js'

const { getters, dispatch } = Store;
const { ERR_OK, ERR_FALSE, app } = Config;
const { dateFormat, time2seconds, convertUrlQueryObject, rgb2hex, rgba2hex, uncode } = Utils;
const context = {
	request,
	HTMLParser,
	gb2312,
	Base64,
	Single,
	Gather,
	Character,
	Section,
	Comment,
	Barrage,
	replaceHTML,
	htmlDecodeByRegExp,
	dateFormat,
	convertUrlQueryObject,
	time2seconds,
	uncode,
	rgb2hex,
	rgba2hex,
	CryptoJS,
	regmatchhtml,
	regmatchstr
}

const detailArr = ['getSingleDetail', 'getCharacterDetail', 'getGatherDetail']
let detailResponse = null

//返回数据
function resolveData({
	code,
	msg,
	requestResult,
	response,
	source
}) {
	let results = {
		code: code,
		msg: msg,
		request: requestResult.name || 'undefined',
		requestName: requestResult.label || '未知请求',
		requestMethod: requestResult.method ? requestResult.method.toUpperCase() : 'NONE',
		requestUrl: requestResult.url || null,
		requestData: requestResult.data || {},
		requestHeader: requestResult.header || {},
		source: source.id,
		sourceTitle: source.title,
		responseData: requestResult.params || {},
		result: requestResult.result || {},
		data: response || {}
	}
	if ( detailArr.indexOf(requestResult.name.split('_')[0]) > -1 ) detailResponse = requestResult
	if ( getters['debug/get'] ) dispatch('debug/incNetwork', results)
	return results
}

//请求成功回调
function success (requestHandle, source, requestResult, cum, res, resolve) {
	if ( requestResult.value.indexOf('return new Promise') > -1 ) {
		requestHandle(Object.assign({}, context, cum), requestResult.data, res).then(data => {
			resolve(
				resolveData({
					code: ERR_OK,
					msg: 'ok',
					requestResult: requestResult,
					response: data,
					source: source
				})
			)
		}).catch(err => {
			fail(source, requestResult, err, resolve)
		})
	} else {
		resolve(
			resolveData({
				code: ERR_OK,
				msg: 'ok',
				requestResult: requestResult,
				response: requestHandle(Object.assign({}, context, cum), requestResult.data, res),
				source: source
			})
		)
	}
}

//请求失败回调
function fail (source, requestResult, err, resolve) {
	resolve(
		resolveData({
			code: ERR_FALSE,
			msg: err.message,
			requestResult: requestResult,
			response: null,
			source: source
		})
	)
}

//生成请求
export function prepose(source, name, data) {
	let cum = {}
	let urlHandle = null
	let paramsHandle = null
	let headersHandle = null
	let requestHandle = null
	let requestResult = {
		name: name,
		data: data
	}
	return new Promise(resolve => {
		try{
			let sourceHandle = source.text ? eval("(" + source.text + ")") : source
			if ( sourceHandle.custom ) cum = sourceHandle.custom
			if ( sourceHandle.request[name].method != 'none' ) {
				urlHandle = sourceHandle.request[name].url || function () { return data.baseUrl }
				paramsHandle = sourceHandle.request[name].params || function () { return {} }
				headersHandle = sourceHandle.request[name].headers || function () { return {} }
			}
			requestHandle = sourceHandle.request[name].value
			requestResult.label = sourceHandle.request[name].label
			requestResult.method = sourceHandle.request[name].method
			requestResult.value = sourceHandle.request[name].value.toString()
			let interval = sourceHandle.request[name].interval || source.interval || 0
			setTimeout(() => {
				try{
					if ( sourceHandle.request[name].method != 'none' ) {
						let url = urlHandle(Object.assign({}, context, cum), data)
						let params = paramsHandle(Object.assign({}, context, cum), data)
						let headers = headersHandle(Object.assign({}, context, cum), data)
						requestResult.url = url
						requestResult.params = params
						requestResult.header = headers
						if ( sourceHandle.request[name].inherit && detailResponse && detailResponse.data.source == data.source && detailResponse.data.id == data.id ) {
							requestResult.result = detailResponse.result
							success(requestHandle, source, requestResult, cum, detailResponse.result, resolve)
						} else {
							for (var k in params) {
							    let value = params[k] !== undefined ? params[k] : ''
							    requestResult.url += `&${k}=${encodeURIComponent(value)}`
							}
							request[source.request[name].charset == 'utf8' ? 'http' : 'xhr'][source.request[name].method](url, {
								params: params,
								mimeType: headers?.mimeType || (source.request[name].charset == 'gbk' ? 'text/html;charset=gb2312' : null),
								headers: Object.assign({}, {
									Referer: data.baseUrl,
									Charset: source.request[name].method
								}, headers)
							}).then(res => {
								requestResult.result = res
								success(requestHandle, source, requestResult, cum, res, resolve)
							}).catch(err => {
								fail(source, requestResult, err, resolve)
							})
						}
					} else {
						success(requestHandle, source, requestResult, cum, null, resolve)
					}
				} catch(err){
					fail(source, requestResult, err, resolve)
				}
			}, interval)
		}catch(err){
			fail(source, requestResult, err, resolve)
		}
	})
}


//统合请求前置方法
export function com_prepose (requests) {
	let newArr = [];
	requests.forEach(request => {
		newArr.push(
			sin_prepose(request.data, request.name)
		)
	})
	return Promise.all(newArr.map((promise)=>promise.catch((e)=>{promise.resolve(e)})))
}

//单独请求前置方法
export function sin_prepose (data, name) {
	data = JSON.parse(JSON.stringify(data || {}))
	const sources = inSources.concat(getters['source/get'])
	let index = sources.findIndex(source => source.id == data.source)
	try{
		let source = sources[index]
		data.baseUrl = source.href
		return prepose(source, name, data)
	}catch(err) {
		return new Promise(resolve => {
			fail({
				id: data.source,
				title: app.name,
				logo: app.logo
			}, { name: name, data: data}, err, resolve)
		})
	}
}

/**
 * 去除html字符串的无关内容
 * @param {Number} html html字符串
*/
function replaceHTML (html) {
	let str = html;//将html转化为字符
	str = str.replace(/\n/g,'');//去除\n
	str = str.replace(/\r/g,'');//去除\r
	str = str.replace(/\t/g,'');//去除\t
	str = str.replace(/&nbsp;/g,'');//去除&nbsp;
	str = str.replace(/\\/g,'');//去除掉无关的斜杠
	return str;
}

//转义html特殊字符
function htmlDecodeByRegExp (str) {
	let s = ""
	if (str.length == 0) return ""
	s = str.replace(/&#x/g, "\\u")
	s = s.replace(/&#58;/g, ":")
	s = s.replace(/&#32;/g, " ")
	s = s.replace(/&#33;/g, "!")
	s = s.replace(/&#34;/g, '"')
	s = s.replace(/&#35;/g, "#")
	s = s.replace(/&#36;/g, "$")
	s = s.replace(/&#37;/g, "%")
	s = s.replace(/&#38;/g, "&")
	s = s.replace(/&#39;/g, "'")
	s = s.replace(/&#40;/g, "(")
	s = s.replace(/&#41;/g, ")")
	s = s.replace(/&#42;/g, "*")
	s = s.replace(/&#43;/g, "+")
	s = s.replace(/&#44;/g, ",")
	s = s.replace(/&#45;/g, "-")
	s = s.replace(/&#46;/g, ".")
	s = s.replace(/&#47;/g, "/")
	s = s.replace(/&#13;/g, "\n")
	s = s.replace(/<br\/>/g, "\n")
	s = s.replace(/<br \/>/g, "\n")
	s = s.replace(/<br>/g, "\n")
	s = s.replace(/&amp;/g, "")
	s = s.replace(/&nbsp;/g, " ")
	s = s.replace(/&#8211;/g, "–")
	s = s.replace(/#65279;/g, "")
	s = s.replace(/&hellip;/g, '...')
	s = s.replace(/&mdash;/g, '—')
	s = s.replace(/&ldquo;/g, "“")
	s = s.replace(/&rdquo;/g, "”")
	s = s.replace(/&middot;/g, ".")
	s = s.replace(/&iexcl;/g, "¡")
	s = s.replace(/&cent;/g, "¢")
	s = s.replace(/&pound;/g, "£")
	s = s.replace(/&curren;/g, "¤")
	s = s.replace(/&yen;/g, "¥")
	s = s.replace(/&sect;/g, "§")
	s = s.replace(/&uml;/g, "¨")
	s = s.replace(/&copy;/g, "©")
	s = s.replace(/&ordf;/g, "ª")
	s = s.replace(/&laquo;/g, "«")
	s = s.replace(/&not;/g, "¬")
	s = s.replace(/&reg;/g, "®")
	s = s.replace(/&macr;/g, "¯")
	s = s.replace(/&deg;/g, "°")
	s = s.replace(/&plusmn;/g, "±")
	s = s.replace(/&acute;/g, "´")
	s = s.replace(/&micro;/g, "µ")
	s = s.replace(/&para;/g, "¶")
	s = s.replace(/&middot;/g, "·")
	s = s.replace(/&cedil;/g, "¸")
	s = s.replace(/&ordm;/g, "º")
	s = s.replace(/&raquo;/g, "»")
	s = s.replace(/&iquest;/g, "¿")
	s = s.replace(/&Agrave;/g, "À")
	s = s.replace(/&Aacute;/g, "Á")
	s = s.replace(/&Acirc;/g, "Â")
	s = s.replace(/&Atilde;/g, "Ã")
	s = s.replace(/&Auml;/g, "Ä")
	s = s.replace(/&Aring;/g, "Å")
	s = s.replace(/&AElig;/g, "Æ")
	s = s.replace(/&Ccedil;/g, 'Ç')
	s = s.replace(/&Egrave;/g, "È")
	s = s.replace(/&Eacute;/g, "É")
	s = s.replace(/&Ecirc;/g, "Ê")
	s = s.replace(/&Euml;/g, "Ë")
	s = s.replace(/&Igrave;/g, "Ì")
	s = s.replace(/&Iacute;/g, "Í")
	s = s.replace(/&Icirc;/g, "Î")
	s = s.replace(/&Iuml;/g, "Ï")
	s = s.replace(/&Ntilde;/g, "Ñ")
	s = s.replace(/&Ograve;/g, "Ò")
	s = s.replace(/&Oacute;/g, "Ó")
	s = s.replace(/&Ocirc;/g, "Ô")
	s = s.replace(/&Otilde;/g, "Õ")
	s = s.replace(/&Ouml;/g, "Ö")
	s = s.replace(/&Oslash;/g, "Ø")
	s = s.replace(/&Ugrave;/g, "Ù")
	s = s.replace(/&Uacute;/g, "Ú")
	s = s.replace(/&Ucirc;/g, "Û")
	s = s.replace(/&Uuml;/g, "Ü")
	s = s.replace(/&szlig;/g, "ß")
	s = s.replace(/&agrave;/g, "à")
	s = s.replace(/&aacute;/g, "á")
	s = s.replace(/&acirc;/g, "â")
	s = s.replace(/&atilde;/g, "ã")
	s = s.replace(/&auml;/g, "ä")
	s = s.replace(/&aring;/g, "å")
	s = s.replace(/&aelig;/g, "æ")
	s = s.replace(/&ccedil;/g, "ç")
	s = s.replace(/&egrave;/g, "è")
	s = s.replace(/&eacute;/g, "é")
	s = s.replace(/&ecirc;/g, "ê")
	s = s.replace(/&euml;/g, "ë")
	s = s.replace(/&igrave;/g, "ì")
	s = s.replace(/&iacute;/g, "í")
	s = s.replace(/&icirc;/g, "î")
	s = s.replace(/&iuml;/g, "ï")
	s = s.replace(/&ntilde;/g, "ñ")
	s = s.replace(/&ograve;/g, "ò")
	s = s.replace(/&oacute;/g, "ó")
	s = s.replace(/&ocirc;/g, "ô")
	s = s.replace(/&otilde;/g, "õ")
	s = s.replace(/&ouml;/g, "ö")
	s = s.replace(/&divide;/g, "÷")
	s = s.replace(/&oslash;/g, "ø")
	s = s.replace(/&ugrave;/g, "ù")
	s = s.replace(/&uacute;/g, "ú")
	s = s.replace(/&ucirc;/g, "û")
	s = s.replace(/&uuml;/g, "ü")
	s = s.replace(/&yuml;/g, "ÿ")
	return s;
}

//正则匹配html标签
function regmatchhtml ( {
	html,
	label,
	attribute,
	value,
	matched = '',
	nums = {},
	num = 1,
	index = 0
} ) {
	let match,
		reg,
		starts,
		arr,
		str,
		time,
		pos
	reg = new RegExp(eval( attribute ? `/<${label}[^>]*${attribute}=([(''|"")]?)${value}\\1[^>]*>/ig` : `/<${label}[^>]*>/ig`));
	starts = []
	while ( (match = reg.exec(html)) != null ) {
		starts.push({
			index: match.index,
			value: match[0]
		})
	}
	arr = []
	Object.keys(starts).forEach(key => {
		str = html.slice(starts[key].index, parseInt(key) + 1 > starts.length - 1 ? html.length : starts[parseInt(key) + 1].index)
		time = 0
		reg = new RegExp(eval(`/<\\/${label}>/ig`));
		while ( (match = reg.exec(str)) != null && !arr[key] ) {
			time++
			pos = nums[key] || num
			if ( pos == time ) {
				arr.push(str.slice(0, match.index + match[0].length))
			}
		}
	})
	if ( arr.length > 0 ) {
		if ( matched.indexOf('g') > -1 ) {
			return arr
		} else {
			let first = arr[index]
			let second = first.replace(eval(attribute ? `/<${label}[^>]*${attribute}=([(''|"")]?)${value}\\1[^>]*>/` : `/<${label}[^>]*>/`), '')
			reg = new RegExp(eval(`/<\\/${label}>/ig`));
			let endLabels = []
			while ( (match = reg.exec(second)) != null ) {
				if ( pos == time ) {
					endLabels.push({
						index: match.index,
						value: match[0]
					})
				}
			}
			second = second.slice(0, endLabels[endLabels.length - 1].index)
			return [first, second]
		}
	} else {
		return arr
	}
}

//正则匹配2个指定字符之间的内容
function regmatchstr ({
	str,
	start,
	end,
	matched = '',
	index = 0
}) {
	start = start.replace(/(?=\\)/g, '\\')
	start = start.replace(/(?=\/)/g, '\\')
	end = end.replace(/(?=\\)/g, '\\')
	end = end.replace(/(?=\/)/g, '\\')
	let arr = str.match(eval(`/${start}*([\\s\\S]*?)${end}/ig`))
	return arr ? matched.indexOf('g') > -1 ? arr : arr[index].match(eval(`/${start}*([\\s\\S]*?)${end}/`)) : null
}